package by.vr.jpa.result.transformer.impl;

import java.lang.reflect.Method;
import java.util.HashSet;

import javax.persistence.Transient;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import by.vr.jpa.result.transformer.exception.LazyPropertyException;
import by.vr.jpa.result.transformer.util.PropertyUtils;

import com.google.common.collect.Sets;

public class LazyEntityInterceptor implements MethodInterceptor {
	
	
	private HashSet<String> initializedProperties = Sets.newHashSetWithExpectedSize(5);
	
	

	public Object intercept(Object object, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		final String methodName = method.getName();
		final String propertyName = by.vr.jpa.result.transformer.util.PropertyUtils.getPropertyName(methodName);
		if(PropertyUtils.isGetter(methodName)){
			if(!isInitialized(propertyName) && !isTransient(method)){
				throw new LazyPropertyException("Property " + propertyName +   " is not initialized or marked as @Transient");
			}
			
			
		}else if (PropertyUtils.isSetter(methodName)){
			initializedProperties.add(propertyName);
		}		

		final Object returnValue = methodProxy.invokeSuper(object, args);
		return returnValue;

	}
	
	
	
	
	
	protected boolean isInitialized(String propertyName){
		return initializedProperties.contains(propertyName) || "class".equals(propertyName) ;
	}
	
	
	protected boolean isTransient(Method method){
		return method.getAnnotation(Transient.class) != null;
	}

}
